/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

#include "../../stdafx.h"
#include "../../include/grid/FCTree.h"

namespace FaceCat{
	FCTree::FCTree(){
		setGridLineColor(FCColor_None);
		m_checkBoxes = false;
		m_checkBoxSize.cx = 14;
		m_checkBoxSize.cy = 14;
		m_movingNode = 0;
		m_nodeSize.cx = 14;
		m_nodeSize.cy = 14;
	}

	FCTree::~FCTree(){
		m_movingNode = 0;
		m_nodes.clear();
	}

	bool FCTree::hasCheckBoxes(){
		return m_checkBoxes;
	}

	void FCTree::setCheckBoxes(bool value){
		m_checkBoxes = value;
	}

	FCSize FCTree::getCheckBoxSize(){
		return m_checkBoxSize;
	}

	void FCTree::setCheckBoxSize(FCSize value){
		m_checkBoxSize = value;
	}

	String FCTree::getCheckedImage(){
		return m_checkedImage;
	}

	void FCTree::setCheckedImage(const String& value){
		m_checkedImage = value;
	}

	String FCTree::getCollapsedNodeImage(){
		return m_collapsedNodeImage;
	}

	void FCTree::setCollapsedNodeImage(const String& value){
		m_collapsedNodeImage = value;
	}

	String FCTree::getExpendedNodeImage(){
		return m_expendedNodeImage;
	}

	void FCTree::setExpendedNodeImage(const String& value){
		m_expendedNodeImage = value;
	}

	FCSize FCTree::getNodeSize(){
		return m_nodeSize;
	}

	void FCTree::setNodeSize(FCSize value){
		m_nodeSize = value;
	}

	ArrayList<FCTreeNode*> FCTree::getSelectedNodes(){
		ArrayList<FCTreeNode*> selectedNodes;
		ArrayList<FCGridRow*> selectedRows = getSelectedRows();
		int selectedRowsSize = (int)selectedRows.size();
		for(int i = 0; i < selectedRowsSize; i++){
			ArrayList<FCGridCell*> cells = selectedRows.get(i)->m_cells;
            int cellsSize = (int)cells.size();
            for (int j = 0; j < cellsSize; j++){
                FCTreeNode *node = dynamic_cast<FCTreeNode*>(cells.get(j));
                if (node){
                    selectedNodes.add(node);
                    break;
                }
            }
		}
		return selectedNodes;
	}

	void FCTree::setSelectedNodes(ArrayList<FCTreeNode*> value){
		int selectedNodesSize = (int)value.size();
		ArrayList<FCGridRow*> selectedRows;
		for(int i = 0; i < selectedNodesSize; i++){
			selectedRows.add(value.get(i)->getRow());
		}
		setSelectedRows(selectedRows);
	}

	String FCTree::getUnCheckedImage(){
		return m_unCheckedImage;
	}

	void FCTree::setUnCheckedImage(const String& value){
		m_unCheckedImage = value;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	void FCTree::appendNode(FCTreeNode *node){
		node->setTree(this);
		node->onAddingNode(-1);
		m_nodes.add(node);
	}

	void FCTree::clearNodes(){
		while((int)m_nodes.size() > 0){
			removeNode(m_nodes.get((int)m_nodes.size() - 1));
		}
	}

	void FCTree::collapse(){
		int nodesSize = (int)m_nodes.size();
		if (nodesSize > 0){
			for(int i = 0; i < nodesSize; i++){
				m_nodes.get(i)->collapse();
			}
		}
	}

	void FCTree::collapseAll(){
		int nodesSize = (int)m_nodes.size();
		if (nodesSize > 0){
			for (int i = 0; i < nodesSize; i++){
				m_nodes.get(i)->collapseAll();
			}
		}
	}

	void FCTree::expend(){
		int nodesSize = (int)m_nodes.size();
		if (nodesSize > 0){
			for(int i = 0; i < nodesSize; i++){
				m_nodes.get(i)->expend();
			}
		}
	}

	void FCTree::expendAll()
	{
		int nodesSize = (int)m_nodes.size();
		if (nodesSize > 0){
			for (int i = 0; i < nodesSize; i++){
				m_nodes.get(i)->expendAll();
			}
		}
	}

	ArrayList<FCTreeNode*> FCTree::getChildNodes(){
		return m_nodes;
	}

	String FCTree::getViewType(){
		return L"Tree";
	}

	int FCTree::getNodeIndex(FCTreeNode *node){
		int size = (int)m_nodes.size();
		for(int i = 0; i < size; i++){
			if(m_nodes.get(i) == node){
				return i;
			}
		}
		return -1;
	}

	void FCTree::getAttribute(const String& name, String *value, String *type){
		if(name == L"checkboxes"){
			*type = L"bool";
			*value = FCTran::boolToStr(hasCheckBoxes());
		}
		else if(name == L"checkboxsize"){
			*type = L"size";
			*value = FCTran::sizeToStr(getCheckBoxSize());
		}
		else if (name == L"checkedimage"){
            *type = L"text";
            *value = getCheckedImage();
        }
        else if (name == L"collapsednodeimage"){
            *type = L"text";
            *value = getCollapsedNodeImage();
        }
        else if (name == L"expendednodeimage"){
            *type = L"text";
            *value = getExpendedNodeImage();
        }
        else if (name == L"uncheckedimage") {
            *type = L"text";
            *value = getUnCheckedImage();
        }
		else if(name == L"nodesize"){
			*type = L"size";
			*value = FCTran::sizeToStr(getNodeSize());
		}
		else{
			FCGrid::getAttribute(name, value, type);
		}
	}

	ArrayList<String> FCTree::getAttributeNames(){
		ArrayList<String> attributeNames = FCGrid::getAttributeNames();
		attributeNames.add(L"CheckBoxes");
		attributeNames.add(L"CheckBoxSize");
		attributeNames.add(L"CheckedImage");
		attributeNames.add(L"CollapsedNodeImage");
		attributeNames.add(L"ExpendedNodeImage");
		attributeNames.add(L"UnCheckedImage");
		attributeNames.add(L"NodeSize");
		return attributeNames;
	}

	void FCTree::insertNode(int index, FCTreeNode *node){
	    int rowIndex = -1;
        if (index == 0){
            if (node->getParent()){
                rowIndex = node->getParent()->getRow()->getIndex() + 1;
            }
			rowIndex = 0;
        }
        else{
            if (m_nodes.size() > 0){
                rowIndex = m_nodes.get(index)->getRow()->getIndex();
            }
        }
        node->setTree(this);
        node->onAddingNode(rowIndex);
        m_nodes.insert(index, node);
	}

	void FCTree::onCellTouchDown(FCGridCell *cell, FCTouchInfo touchInfo){
		FCTreeNode *oldSelectedNode = 0;
        ArrayList<FCTreeNode*> selectedNodes = getSelectedNodes();
        if(selectedNodes.size() > 0){
            oldSelectedNode = selectedNodes.get(0);
        }
        FCHost *host = getNative()->getHost();
        FCGrid::onCellTouchDown(cell, touchInfo);
        if(touchInfo.m_firstTouch){
            FCPoint mp = touchInfo.m_firstPoint;
            FCTreeNode *node = dynamic_cast<FCTreeNode*>(cell);
            if (node){
                int scrollH = 0;
                FCHScrollBar *hscrollBar = getHScrollBar();
                if (hscrollBar && hscrollBar->isVisible()){
                    scrollH = hscrollBar->getPos();
                }
                FCRect headerRect = node->getTargetColumn()->getBounds();
                headerRect.left += getHorizontalOffset() - scrollH;
                headerRect.top += getVerticalOffset() - scrollH;
                int left = headerRect.left;
                if (m_checkBoxes){
                    int cw = m_checkBoxSize.cx;
                    if (mp.x >= left && mp.x <= left + cw){
                        if (host->isKeyPress(VK_SHIFT) && oldSelectedNode && oldSelectedNode != node){
                            int sIndex = oldSelectedNode->getRow()->getIndex();
                            int eIndex = node->getRow()->getIndex();
                            int minIndex = FCTran::minValue(sIndex, eIndex);
                            int maxIndex = FCTran::maxValue(eIndex, eIndex);
                            for(int i = minIndex; i <= maxIndex; i++){
                                FCTreeNode *iNode = (FCTreeNode*)m_rows.get(i)->getCell(0);
                                iNode->setChecked(oldSelectedNode->isChecked());
                            }
                        }else{
                            node->setChecked(!node->isChecked());
                        }
                        return;
                    }
                    left += cw + 10;
                }
                ArrayList<FCTreeNode*> childNodes = node->getChildNodes();
                if (childNodes.size() > 0){
                    int nw = m_nodeSize.cx;
                    if (mp.x >= left && mp.x <= left + nw){
                        if (node->isExpended()){
                            node->collapse();
                        }
                        else{
                            node->expend();
                        }
                        update();
                        return;
                    }
                }
            }
        }
	}

	void FCTree::onCellTouchMove(FCGridCell *cell, FCTouchInfo touchInfo){
		FCGrid::onCellTouchMove(cell, touchInfo);
		if (touchInfo.m_firstTouch)
        {
            if (!m_movingNode)
            {
                FCPoint mp = touchInfo.m_firstPoint;
                FCTreeNode *node = dynamic_cast<FCTreeNode*>(cell);
                if (node && node->allowDragOut())
                {
                    if (abs(m_touchDownPoint.y - mp.y) > 5)
                    {
                        m_movingNode = node;
                    }
                }
            }
            if (m_movingNode)
            {
                invalidate();
            }
        }
	}

	void FCTree::onCellTouchUp(FCGridCell *cell, FCTouchInfo touchInfo){
		FCGrid::onCellTouchUp(cell, touchInfo);
		FCPoint mp = touchInfo.m_firstPoint;
		if (m_movingNode){
            FCGridRow *curRow = getRow(mp);
            if (curRow){
				FCTreeNode *curNode = dynamic_cast<FCTreeNode*>(curRow->getCell(0));
                if (curNode->allowDragIn() && m_movingNode != curNode){
					bool isParent = false;
                    FCTreeNode *parentNode = curNode->getParent();
                    if (parentNode == m_movingNode)
                    {
                        isParent = true;
                    }
                    else
                    {
                        while (parentNode)
                        {
                            parentNode = parentNode->getParent();
                            if (parentNode == m_movingNode)
                            {
                                isParent = true;
                                break;
                            }
                        }
                    }
                    if (!isParent)
                    {
                        FCTreeNode *curNodeParent = curNode->getParent();
                        FCTreeNode *movingNodeParent = m_movingNode->getParent();
                        if (movingNodeParent)
                        {
                            movingNodeParent->removeNode(m_movingNode);
                        }
                        else
                        {
                            removeNode(m_movingNode);
                        }
                        curNode->appendNode(m_movingNode);
                        curNode->expend();
                    }
                }
            }
            m_movingNode = 0;
			update();
        }
	}

	void FCTree::onPaintForeground(FCPaint *paint, const FCRect& clipRect){
		FCGrid::onPaintForeground(paint, clipRect);
		if (m_movingNode){
			FCFont *font = getFont();
            FCPoint mp = getTouchPoint();
			FCSize tSize = paint->textSize(m_movingNode->getText(), font, -1);
			FCRect tRect = {mp.x, mp.y, mp.x + tSize.cx, mp.y + tSize.cy};
			paint->fillRect(getBackColor(), tRect);
            paint->drawRect(getTextColor(), 1, 0, tRect);
            paint->drawText(m_movingNode->getText(), getTextColor(), font, tRect, -1);
        }
	}

	void FCTree::onPaintEditTextBox(FCGridCell *cell, FCPaint *paint, const FCRect& rect, const FCRect& clipRect){
		FCTextBox *editTextBox = getEditTextBox();
        if (editTextBox){
            FCTreeNode *node = dynamic_cast<FCTreeNode*>(cell);
            if (node){
                int indent = node->getIndent();
				FCRect newRect = rect;
                newRect.left += indent;
                if (newRect.right < newRect.left){
                    newRect.right = newRect.left;
                }
                editTextBox->setBounds(newRect);
                editTextBox->setDisplayOffset(false);
                editTextBox->bringToFront();
            }
			else{
				FCGrid::onPaintEditTextBox(cell, paint, rect, clipRect);
			}
        }
	}

	void FCTree::removeNode(FCTreeNode *node){
		node->onRemovingNode();
		for(int i = 0; i < m_nodes.size(); i++){
			FCTreeNode *tn = m_nodes.get(i);
			if(tn == node){
				m_nodes.removeAt(i);
				break;
			}
		}
	}

	void FCTree::setAttribute(const String& name, const String& value){
		if(name == L"checkboxes"){
			setCheckBoxes(FCTran::strToBool(value));
		}
		else if(name == L"checkboxsize"){
			setCheckBoxSize(FCTran::strToSize(value));
		}
	    else if (name == L"checkedimage"){
            setCheckedImage(value);
        }
        else if (name == L"collapsednodeimage"){
            setCollapsedNodeImage(value);
        }
        else if (name == L"expendednodeimage"){
            setExpendedNodeImage(value);
        }
        else if (name == L"uncheckedimage"){
            setUnCheckedImage(value);
        }
		else if(name == L"nodesize"){
			setNodeSize(FCTran::strToSize(value));
		}
		else{
			FCGrid::setAttribute(name, value);
		}
	}
}